package my.edu.model.information.service;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import my.edu.common.constant.MessageConstant;
import my.edu.common.exception.CanNotFoundException;
import my.edu.common.exception.CategoryException;
import my.edu.common.exception.SaveException;
import my.edu.common.exception.UpdateException;
import my.edu.model.information.entity.VO.CustomerCategoryVO;
import my.edu.model.information.entity.dto.CustomerCategoryDTO;
import org.springframework.stereotype.Service;
import my.edu.model.information.entity.CustomerCategory;
import my.edu.model.information.mapper.CustomerCategoryMapper;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class CustomerCategoryServiceImpl extends ServiceImpl<CustomerCategoryMapper, CustomerCategory> implements ICustomerCategoryService {

    @Override
    @Transactional
    public void savenew(CustomerCategoryDTO customerCategoryDTO) {
        CustomerCategory customerCategory = BeanUtil.copyProperties(customerCategoryDTO, CustomerCategory.class);
        customerCategory.setStatus(1);
        customerCategory.setIsParentCategory(0);
        customerCategory.setVersion(1);
        boolean updateNewParent=true;
        if (customerCategory.getParentId() != 0)
            updateNewParent=checkParentAndUpdate(customerCategory, true);
       if (updateNewParent)save(customerCategory);
       else throw new SaveException(MessageConstant.SAVE_FAIL);
    }

    @Override
    public List<CustomerCategoryVO> listAll() {
        List<CustomerCategory> list = list();
        List<CustomerCategoryVO> categories = list.stream().map(i -> BeanUtil.copyProperties(i, CustomerCategoryVO.class)).collect(Collectors.toList());
        List<CustomerCategoryVO> res = new ArrayList<>();
        for (CustomerCategoryVO category : categories) {
            if (category.getParentId() == 0) {
                //是一层父类，构建子类列表
                buildChildren(category, categories);
                res.add(category);
            }
        }
        return res;
    }

    @Override
    @Transactional
    public void updateByDTO(CustomerCategoryDTO customerCategoryDTO) {
        //加了Transactional可以在执行了updateById但是没有修改数据库的时候不能修改对应数据
        //加乐观锁可以保证在查询到对应数据和更新数据期间没有覆盖别的数据
        boolean updateOriginalParent=true;
        boolean updateNewParent=true;
        CustomerCategory original = getById(customerCategoryDTO.getId());
        //存在校验
        if (original == null) throw new CanNotFoundException(MessageConstant.CAN_NOT_FOUND);
        CustomerCategory newCategory = BeanUtil.copyProperties(customerCategoryDTO, CustomerCategory.class);
        //将父类变成其他的，查看原先父类是否有其他子类，没有了就改isParentCategory为0
        if (!Objects.equals(newCategory.getParentId(), original.getParentId())) {
            //检查原来父类
            updateOriginalParent = checkParentAndUpdate(original,  false);
            //检查修改之后的父类
            updateNewParent=checkParentAndUpdate(newCategory, true);
        }
       newCategory.setVersion(original.getVersion());
        boolean updateCategory = updateById(newCategory);
        if ( !updateOriginalParent || !updateNewParent || !updateCategory ) throw new UpdateException(MessageConstant.UPDATE_FAIL);
    }

    private boolean checkParentAndUpdate(CustomerCategory childCategory,boolean isTurnToParent) {
        //如果检查的是修改之后的父类，则当count为0，表示此父类没有子类，所以修改子类的父类id之后，此父类的IsParentCategory值为1
        long count =0L;
        int targetValue=1;
        if (!isTurnToParent) {
            count=1L;
            targetValue=0;
        }
        boolean b =true;//代表是否检查并更新成功
        CustomerCategory parentCategory;
        //获取所有父id是当前父id的元素
        Long parentCount = lambdaQuery()
                .eq(CustomerCategory::getParentId, childCategory.getParentId())
                .count();
        //检查父类的子类个数，当isTurnToParent，如果parentCount为0，则新增之后要变为1
        // 否则当parentCount为1，子类修改为别的父类的时候，要将父类的IsParentCategory变为0
        if (Objects.equals(parentCount, count)) {
            //获取父id的元素
            parentCategory=lambdaQuery()
                    .eq(CustomerCategory::getId, childCategory.getParentId()).one();
            if (parentCategory==null)throw new CategoryException(MessageConstant.FUCATEGORIES_NOT_FOUND);
            parentCategory.setIsParentCategory(targetValue);
            b = updateById(parentCategory);
        }
        return b;
    }

    private void buildChildren(CustomerCategoryVO parent, List<CustomerCategoryVO> allCategories) {
        if (parent.getIsParentCategory().equals(0))return;
        List<CustomerCategoryVO> children = new ArrayList<>();
        for (CustomerCategoryVO category : allCategories) {
            if (category.getParentId() != null && category.getParentId().equals(parent.getId())) {
                buildChildren(category, allCategories);
                children.add(category);
            }
        }
        parent.setCustomerZiCategoryList(children);
    }
}
